local MAJOR_VERSION, MINOR_VERSION = "LibResSync-1.0", 2
local lib = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION)
if not lib then return end

local _G = _G
local UnitExists = _G.UnitExists
local UnitName = _G.UnitName
local GetRealmName = _G.GetRealmName
local SendAddonMessage = _G.SendAddonMessage
local IsInInstance = _G.IsInInstance
local GetNumGroupMembers = _G.GetNumGroupMembers
local GetNumSubgroupMembers = _G.GetNumSubgroupMembers

local mtype, mvalue, uname, urealm

lib.Callbacks = LibStub("CallbackHandler-1.0"):New(lib)
lib.temp = lib.temp or {}
lib.inspectDB = lib.inspectDB or {}
lib.battleGround = lib.battleGround or { pvp = true, arena = true }
lib.castingTarget = lib.castingTarget or {}
lib.corpsePattern = "^"..CORPSE_TOOLTIP:gsub("%%s", "(.+)").."$"
lib.resurrectionSpells = {
	[GetSpellInfo(2006) or ""] = true,
	[GetSpellInfo(2008) or ""] = true,
	[GetSpellInfo(7328) or ""] = true,
	[GetSpellInfo(50769) or ""] = true,
	[GetSpellInfo(20484) or ""] = true,
	[GetSpellInfo(61999) or ""] = true,
	[GetSpellInfo(115178) or ""] = true,
}
lib.resurrectionSpells[""] = nil
lib.playerName = UnitName("player")
lib.playerRealmName = "-"..GetRealmName()
lib.playerFullName = lib.playerName..lib.playerRealmName

lib.EventFrame = lib.EventFrame or CreateFrame("Frame")
lib.EventFrame:SetScript("OnEvent", function(self, event, ...) lib[event](lib, ...) end)
lib.EventFrame:UnregisterAllEvents()
lib.EventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
lib.EventFrame:RegisterEvent("UNIT_SPELLCAST_SENT")
lib.EventFrame:RegisterEvent("UNIT_SPELLCAST_STOP")
lib.EventFrame:RegisterEvent("GROUP_ROSTER_UPDATE")
lib.EventFrame:RegisterEvent("CHAT_MSG_ADDON")

if not lib.hookWorldFrame then
	lib.hookWorldFrame = true
	WorldFrame:HookScript("OnMouseDown", function(self, button)
		if GameTooltip:IsShown() and GameTooltipTextLeft1:GetText() then
			lib.playerMouseover = GameTooltipTextLeft1:GetText():match(lib.corpsePattern) or lib.playerMouseover
		end
	end)
end

function lib:SendAddonMessage(info, content, whisper)
	if info and content then
		content = info.."="..content
		if whisper then
			SendAddonMessage("LibResSync", content, "WHISPER", whisper)
		elseif IsInGroup(LE_PARTY_CATEGORY_INSTANCE) and IsInInstance() then
			SendAddonMessage("LibResSync", content, "INSTANCE_CHAT")
		elseif IsInGroup(LE_PARTY_CATEGORY_HOME) then
			if IsInRaid() then
				SendAddonMessage("LibResSync", content, "RAID")
			else
				SendAddonMessage("LibResSync", content, "PARTY")
			end
		end
	end
end

function lib:GetUnitName(unit)
	if unit then
		uname, urealm = UnitName(unit)
		if uname then
			if urealm and urealm ~= "" then
				return uname.."-"..urealm
			else
				return uname
			end
		end
	end
	return nil
end

function lib:UNIT_SPELLCAST_SENT(unit, spellName, spellRank, target)
	if unit == "player" then
		if lib.resurrectionSpells[spellName] then
			if (target == nil or target == COMBATLOG_UNKNOWN_UNIT) and lib.playerMouseover then
				target = lib.playerMouseover
				lib.playerMouseover = nil
			end
			if target and target ~= "" and target ~= COMBATLOG_UNKNOWN_UNIT then
				lib.castingTarget[lib.playerName] = target
				lib:SendAddonMessage("RES", target)
			else
				lib.castingTarget[lib.playerName] = nil
			end
		else
			lib.castingTarget[lib.playerName] = nil
		end
	end
end

function lib:UNIT_SPELLCAST_STOP(unit)
	lib.castingTarget[lib:GetUnitName(unit) or ""] = nil
end

function lib:GROUP_ROSTER_UPDATE()
	for name in pairs(lib.castingTarget) do
		if not UnitExists(name) then
			lib.castingTarget[name] = nil
		end
	end
end

function lib:CHAT_MSG_ADDON(prefix, msg, distribution, sender)
	if prefix == "LibResSync" and sender then
		sender = sender:gsub(lib.playerRealmName, "")
		mtype, mvalue = msg:match("(.+)=(.+)")
		mtype = mtype or msg
		if mtype == "RES" then
			if mvalue then
				lib.castingTarget[sender] = mvalue:gsub(lib.playerRealmName, "")
				lib.Callbacks:Fire("LibResSync_Resurrection", sender, lib.castingTarget[sender])
			end
		end
	elseif prefix == "CTRA" and sender ~= lib.playerName and msg:find("^RES ") then
		mvalue = msg:match("^RES (.+)$")
		if mvalue and mvalue ~= COMBATLOG_UNKNOWN_UNIT then
			sender = sender:gsub(lib.playerRealmName, "")
			lib.castingTarget[sender] = mvalue:gsub(lib.playerRealmName, "")
			lib.Callbacks:Fire("LibResSync_Resurrection", sender, lib.castingTarget[sender])
		end
	end
end

function lib:GetCastingTarget(caster)
	return lib.castingTarget[caster]
end

function lib:PLAYER_ENTERING_WORLD()
	RegisterAddonMessagePrefix("LibResSync")
end

if IsLoggedIn() then lib:PLAYER_ENTERING_WORLD() end